package wdstruct

import (
	"sync"
	"sync/atomic"
)

type linkHand struct {
	len  int32
	head *linknode
	tail *linknode

	zerolock sync.RWMutex
	headlock sync.RWMutex
	taillock sync.RWMutex
}

type linknode struct {
	data interface{}
	prev *linknode
	next *linknode

	lock sync.RWMutex
}

//New_Double_Link ..创建一个双向链表,函数返回链表的句柄
func New_Double_Link() I_DoduleLink_hand {
	return &linkHand{
		len: 0,
	}
}

func (l *linkHand) GetLen() int32 {
	return atomic.LoadInt32(&l.len)
}

func (l *linkHand) GetHead() (head I_DoduleLink_node) {
	l.headlock.RLock()
	head = l.head
	l.headlock.RUnlock()
	return
}
func (l *linkHand) GetTail() (tail I_DoduleLink_node) {
	l.taillock.RLock()
	tail = l.tail
	l.taillock.RUnlock()
	return
}

func (l *linkHand) AddToHead(data interface{}) I_DoduleLink_node {
	l.zerolock.Lock()
	l.headlock.Lock()
	if atomic.LoadInt32(&l.len) == 0 {
		l.head = &linknode{
			data: data,
		}
		l.tail = l.head
		// l.head.prev = l.head
		// l.head.next = l.head
		atomic.AddInt32(&l.len, 1)
		//l.headlock.Unlock()
		l.headlock.Unlock()
		l.zerolock.Unlock()
		return l.GetHead()
	}
	l.head.lock.Lock()
	l.zerolock.Unlock()
	node := &linknode{
		data: data,
		next: l.head,
	}
	l.head.prev = node
	l.head.lock.Unlock()
	atomic.AddInt32(&l.len, 1)
	l.head = node
	l.headlock.Unlock()
	return l.GetHead()
}
func (l *linkHand) AddToTail(data interface{}) I_DoduleLink_node {
	l.zerolock.Lock()
	l.taillock.Lock()
	if atomic.LoadInt32(&l.len) == 0 {
		l.head = &linknode{
			data: data,
		}
		l.tail = l.head
		// l.head.prev = l.head
		// l.head.next = l.head
		atomic.AddInt32(&l.len, 1)
		l.taillock.Unlock()
		l.zerolock.Unlock()
		return l.GetTail()
	}
	l.tail.lock.Lock()
	l.zerolock.Unlock()
	node := &linknode{
		data: data,
		prev: l.tail,
	}
	l.tail.next = node
	l.tail.lock.Unlock()
	l.tail = node
	atomic.AddInt32(&l.len, 1)
	l.taillock.Unlock()
	return l.GetTail()
}

func (l *linkHand) DeleteFromHead() bool {
	l.zerolock.Lock()
	l.headlock.Lock()
	if atomic.LoadInt32(&l.len) > 2 {
		l.head.next.lock.Lock()
		l.zerolock.Unlock()
		l.head.next.prev = nil
		atomic.AddInt32(&l.len, -1)
		l.head.next.lock.Unlock()
		l.head = l.head.next
		l.headlock.Unlock()
		return true
	}
	if atomic.LoadInt32(&l.len) == 2 {
		l.head.next.lock.Lock()
		l.head.next.prev = nil
		atomic.AddInt32(&l.len, -1)
		l.head.next.lock.Unlock()
		l.head = l.head.next
		l.zerolock.Unlock()
		l.headlock.Unlock()
		return true
	} else if atomic.LoadInt32(&l.len) == 1 {
		l.taillock.Lock()
		l.head = nil
		l.tail = nil
		atomic.StoreInt32(&l.len, 0)
		l.taillock.Unlock()
	}
	l.headlock.Unlock()
	l.zerolock.Unlock()
	return true
}
func (l *linkHand) DeletoFromTail() bool {
	l.zerolock.Lock()
	l.taillock.Lock()
	if atomic.LoadInt32(&l.len) > 2 {
		l.tail.prev.lock.Lock()
		l.zerolock.Unlock()
		l.tail.prev.next = nil
		atomic.AddInt32(&l.len, -1)
		l.tail.prev.lock.Unlock()
		l.tail = l.tail.prev
		l.taillock.Unlock()
		return true
	} else if atomic.LoadInt32(&l.len) == 2 {
		l.tail.prev.lock.Lock()
		l.tail.prev.next = nil
		atomic.AddInt32(&l.len, -1)
		l.tail.prev.lock.Unlock()
		l.tail = l.tail.prev
		l.taillock.Unlock()
		l.zerolock.Unlock()
		return true
	} else if atomic.LoadInt32(&l.len) == 1 {
		l.headlock.Lock()
		l.head = nil
		l.tail = nil
		atomic.StoreInt32(&l.len, 0)
		l.headlock.Unlock()
	}
	l.taillock.Unlock()
	l.zerolock.Unlock()
	return true
}

func (l *linknode) GetData() (data interface{}) {
	data = l.data
	return
}
func (l *linknode) GetPrev() (prev I_DoduleLink_node) {
	l.lock.RLock()
	prev = l.prev
	l.lock.RUnlock()
	return
}
func (l *linknode) GetNext() (next I_DoduleLink_node) {
	l.lock.RLock()
	next = l.next
	l.lock.RUnlock()
	return
}
func (l *linknode) IsNull() bool {
	if l == nil {
		return true
	}
	return false
}
